import {
  PromptBuildContext,
  EnhancedCodeContext,
  Memory,
  ToolUsage,
  Guideline,
  Rule,
  ConversationTurn,
  ContextPriority,
  ChatMode
} from './types';

/**
 * 上下文管理器
 * 负责智能地选择和组织提示词上下文信息
 */
export class ContextManager {
  private contextPriority: ContextPriority;

  constructor(contextPriority?: ContextPriority) {
    this.contextPriority = contextPriority || this.getDefaultPriority();
  }

  /**
   * 构建提示词上下文
   */
  buildContext(
    mode: ChatMode,
    userMessage: string,
    options: {
      conversationHistory?: ConversationTurn[];
      codeContext?: EnhancedCodeContext;
      memories?: Memory[];
      toolHistory?: ToolUsage[];
      guidelines?: Guideline[];
      rules?: Rule[];
      variables?: Record<string, any>;
      maxContextLength?: number;
    } = {}
  ): PromptBuildContext {
    const context: PromptBuildContext = {
      mode,
      userMessage,
      conversationHistory: options.conversationHistory || [],
      variables: {
        // Include required template variables
        mode: mode,
        userMessage: userMessage,
        // Merge with any additional variables
        ...(options.variables || {})
      },
      metadata: {}
    };

    // 根据优先级和长度限制添加上下文
    const maxLength = options.maxContextLength || 50000;
    let currentLength = this.estimateLength(context);

    // 按优先级添加上下文
    const contextItems = this.prioritizeContextItems({
      codeContext: options.codeContext,
      memories: options.memories,
      toolHistory: options.toolHistory,
      guidelines: options.guidelines,
      rules: options.rules
    });

    for (const item of contextItems) {
      const itemLength = this.estimateContextItemLength(item);
      
      if (currentLength + itemLength <= maxLength) {
        this.addContextItem(context, item);
        currentLength += itemLength;
      } else {
        // 尝试压缩或截断
        const compressedItem = this.compressContextItem(item, maxLength - currentLength);
        if (compressedItem) {
          this.addContextItem(context, compressedItem);
          break;
        }
      }
    }

    return context;
  }

  /**
   * 优化上下文长度
   */
  optimizeContext(
    context: PromptBuildContext,
    maxLength: number
  ): PromptBuildContext {
    const currentLength = this.estimateLength(context);
    
    if (currentLength <= maxLength) {
      return context;
    }

    // 创建优化后的上下文副本
    const optimized = { ...context };

    // 按优先级逐步减少内容
    if (optimized.conversationHistory && optimized.conversationHistory.length > 0) {
      optimized.conversationHistory = this.truncateConversationHistory(
        optimized.conversationHistory,
        Math.floor(maxLength * 0.3)
      );
    }

    if (optimized.memories && optimized.memories.length > 0) {
      optimized.memories = this.selectTopMemories(
        optimized.memories,
        Math.floor(maxLength * 0.2)
      );
    }

    if (optimized.toolHistory && optimized.toolHistory.length > 0) {
      optimized.toolHistory = this.truncateToolHistory(
        optimized.toolHistory,
        Math.floor(maxLength * 0.15)
      );
    }

    if (optimized.codeContext) {
      optimized.codeContext = this.optimizeCodeContext(
        optimized.codeContext,
        Math.floor(maxLength * 0.25)
      );
    }

    return optimized;
  }

  /**
   * 估算上下文长度
   */
  private estimateLength(context: PromptBuildContext): number {
    let length = 0;
    
    length += context.userMessage.length;
    
    if (context.conversationHistory) {
      length += context.conversationHistory.reduce(
        (sum, turn) => sum + turn.content.length,
        0
      );
    }

    if (context.codeContext) {
      length += this.estimateCodeContextLength(context.codeContext);
    }

    if (context.memories) {
      length += context.memories.reduce(
        (sum, memory) => sum + memory.content.length,
        0
      );
    }

    if (context.toolHistory) {
      length += context.toolHistory.reduce(
        (sum, tool) => sum + JSON.stringify(tool).length,
        0
      );
    }

    return length;
  }

  /**
   * 估算代码上下文长度
   */
  private estimateCodeContextLength(codeContext: EnhancedCodeContext): number {
    let length = 0;

    if (codeContext.currentFile?.content) {
      length += codeContext.currentFile.content.length;
    }

    if (codeContext.selectedCode) {
      length += codeContext.selectedCode.length;
    }

    if (codeContext.workspaceFiles) {
      length += codeContext.workspaceFiles.reduce(
        (sum, file) => sum + (file.content?.length || 0),
        0
      );
    }

    return length;
  }

  /**
   * 按优先级排序上下文项
   */
  private prioritizeContextItems(items: {
    codeContext?: EnhancedCodeContext;
    memories?: Memory[];
    toolHistory?: ToolUsage[];
    guidelines?: Guideline[];
    rules?: Rule[];
  }): Array<{ type: string; data: any; priority: number }> {
    const prioritizedItems: Array<{ type: string; data: any; priority: number }> = [];

    if (items.codeContext) {
      prioritizedItems.push({
        type: 'codeContext',
        data: items.codeContext,
        priority: this.contextPriority.codeContext
      });
    }

    if (items.memories) {
      prioritizedItems.push({
        type: 'memories',
        data: items.memories,
        priority: this.contextPriority.memories
      });
    }

    if (items.toolHistory) {
      prioritizedItems.push({
        type: 'toolHistory',
        data: items.toolHistory,
        priority: this.contextPriority.toolHistory
      });
    }

    if (items.guidelines) {
      prioritizedItems.push({
        type: 'guidelines',
        data: items.guidelines,
        priority: 0.7 // 默认优先级
      });
    }

    if (items.rules) {
      prioritizedItems.push({
        type: 'rules',
        data: items.rules,
        priority: 0.8 // 默认优先级
      });
    }

    return prioritizedItems.sort((a, b) => b.priority - a.priority);
  }

  /**
   * 添加上下文项
   */
  private addContextItem(
    context: PromptBuildContext,
    item: { type: string; data: any }
  ): void {
    switch (item.type) {
      case 'codeContext':
        context.codeContext = item.data;
        break;
      case 'memories':
        context.memories = item.data;
        break;
      case 'toolHistory':
        context.toolHistory = item.data;
        break;
      case 'guidelines':
        context.guidelines = item.data;
        break;
      case 'rules':
        context.rules = item.data;
        break;
    }
  }

  /**
   * 估算上下文项长度
   */
  private estimateContextItemLength(item: { type: string; data: any }): number {
    switch (item.type) {
      case 'codeContext':
        return this.estimateCodeContextLength(item.data);
      case 'memories':
        return item.data.reduce((sum: number, memory: Memory) => 
          sum + memory.content.length, 0);
      case 'toolHistory':
        return item.data.reduce((sum: number, tool: ToolUsage) => 
          sum + JSON.stringify(tool).length, 0);
      default:
        return JSON.stringify(item.data).length;
    }
  }

  /**
   * 压缩上下文项
   */
  private compressContextItem(
    item: { type: string; data: any },
    maxLength: number
  ): { type: string; data: any } | null {
    if (maxLength <= 0) return null;

    switch (item.type) {
      case 'memories':
        return {
          type: item.type,
          data: this.selectTopMemories(item.data, maxLength)
        };
      case 'toolHistory':
        return {
          type: item.type,
          data: this.truncateToolHistory(item.data, maxLength)
        };
      default:
        return null;
    }
  }

  /**
   * 截断对话历史
   */
  private truncateConversationHistory(
    history: ConversationTurn[],
    maxLength: number
  ): ConversationTurn[] {
    const truncated: ConversationTurn[] = [];
    let currentLength = 0;

    // 从最新的对话开始保留
    for (let i = history.length - 1; i >= 0; i--) {
      const turn = history[i];
      if (currentLength + turn.content.length <= maxLength) {
        truncated.unshift(turn);
        currentLength += turn.content.length;
      } else {
        break;
      }
    }

    return truncated;
  }

  /**
   * 选择最相关的记忆
   */
  private selectTopMemories(memories: Memory[], maxLength: number): Memory[] {
    // 按相关性排序
    const sorted = [...memories].sort((a, b) => 
      (b.relevance || 0) - (a.relevance || 0)
    );

    const selected: Memory[] = [];
    let currentLength = 0;

    for (const memory of sorted) {
      if (currentLength + memory.content.length <= maxLength) {
        selected.push(memory);
        currentLength += memory.content.length;
      } else {
        break;
      }
    }

    return selected;
  }

  /**
   * 截断工具历史
   */
  private truncateToolHistory(
    toolHistory: ToolUsage[],
    maxLength: number
  ): ToolUsage[] {
    const truncated: ToolUsage[] = [];
    let currentLength = 0;

    // 从最新的工具使用开始保留
    for (let i = toolHistory.length - 1; i >= 0; i--) {
      const tool = toolHistory[i];
      const toolLength = JSON.stringify(tool).length;
      
      if (currentLength + toolLength <= maxLength) {
        truncated.unshift(tool);
        currentLength += toolLength;
      } else {
        break;
      }
    }

    return truncated;
  }

  /**
   * 优化代码上下文
   */
  private optimizeCodeContext(
    codeContext: EnhancedCodeContext,
    maxLength: number
  ): EnhancedCodeContext {
    const optimized = { ...codeContext };
    let currentLength = this.estimateCodeContextLength(codeContext);

    if (currentLength <= maxLength) {
      return optimized;
    }

    // 优先保留当前文件和选中代码
    if (optimized.workspaceFiles && optimized.workspaceFiles.length > 0) {
      optimized.workspaceFiles = optimized.workspaceFiles.slice(0, 3);
    }

    if (optimized.recentFiles && optimized.recentFiles.length > 0) {
      optimized.recentFiles = optimized.recentFiles.slice(0, 2);
    }

    return optimized;
  }

  /**
   * 获取默认优先级配置
   */
  private getDefaultPriority(): ContextPriority {
    return {
      codeContext: 0.9,
      memories: 0.7,
      toolHistory: 0.6,
      conversationHistory: 0.8,
      dynamicAdjustment: true
    };
  }
}
